﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualStudio.TextTemplating;
using System.IO;
using System.Data.Metadata.Edm;

namespace Cherry.Agile.CodeGenerator
{
    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            InitializeComponent();
        }


        private bool ValidateInput()
        {
            if (string.IsNullOrWhiteSpace(txtNameSpace.Text))
            {
                MessageBox.Show("名称空间不能为空", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ep.SetError(txtNameSpace, "名称空间不能为空");
                txtNameSpace.Focus();
                return false;
            }

            if (string.IsNullOrWhiteSpace(txtModel.Text))
            {
                MessageBox.Show("必须选择一个模型文件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ep.SetError(txtModel, "必须选择一个模型文件");
                txtModel.Focus();
                return false;
            }

            if (string.IsNullOrWhiteSpace(txtEntityOutPut.Text))
            {
                MessageBox.Show("必须设置文件的输出目录", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ep.SetError(txtEntityOutPut, "必须设置文件的输出目录");
                txtEntityOutPut.Focus();
                return false;
            }

            return true;
        }


        private void btnDo_Click(object sender, EventArgs e)
        {
            txtError.Text = string.Empty;

            btnDo.Enabled = false;

            Engine engine = new Engine();

            GeneratEntities(engine,ProjectType.Entity);

            if (chkEntityProject.Checked)
            {
                GenerateProjectFile(engine,ProjectType.Entity);
            }

            btnDo.Enabled = true;
        }

        private void GeneratEntities(Engine engine, ProjectType projectType)
        {
            var host = GetTemplateHost(projectType);
            txtError.Text += "start generate entity class...";

            var result = host.Excute(engine, "{0}");
            string file = Path.Combine(txtEntityOutPut.Text, cmbTemplate.SelectedItem.ToString() + host.fileExtensionValue);
            File.WriteAllText(file, result);

            if (host.Errors.Count > 0)
            {
                txtError.Text += "\r\ngenerate entity class error:";
                foreach (var item in host.Errors)
                {
                    txtError.Text += "\r\n" + item.ToString();
                }
            }
            else
            {
                txtError.Text += "\r\n generate entity class complate";
            }
        }

        private EntityFrameworkTemplateHost GetTemplateHost(ProjectType projectType)
        {
            var host = new EntityFrameworkTemplateHost();
            if (cmbLanguage.SelectedIndex > 0)
            {
                host.fileExtensionValue = ".vb";
            }
            else
            {
                host.fileExtensionValue = ".cs";
            }
            host.Namespace = string.Format("{0}.{1}", txtNameSpace.Text, projectType == ProjectType.Interface ? "Service.Interface": projectType.ToString());
            host.EDMXFile = txtModel.Text;
            //var outputFolder = 
            host.OutputFolder = GetOutputFolder(projectType);
            if(projectType == ProjectType.Entity)
                host.OutputPartialClass = chkOutputPartial.Checked;

            host.TemplateFileValue = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, GetGeneratTemplate( projectType));//
            return host;
        }

        public string GetGeneratTemplate(ProjectType projectType)
        {
            switch(projectType)
            {
                case ProjectType.Entity:
                    return string.Format("{0}.tt", cmbTemplate.SelectedItem);
                case ProjectType.Repository:
                    return string.Format("{0}.tt", projectType.ToString());
                case ProjectType.Service:
                    return string.Format("{0}.tt", projectType.ToString());
                case ProjectType.Interface:
                    return string.Format("{0}.tt", projectType.ToString());
                default:
                    return string.Format("{0}.tt", projectType.ToString());
            }
        }

        private string GetOutputFolder(ProjectType projectType)
        {
            switch(projectType)
            {
                case ProjectType.Entity:
                    return txtEntityOutPut.Text.Trim();
                case ProjectType.Repository:
                    return txtRepositoryOutPut.Text.Trim();
                case ProjectType.Service:
                    return txtServiceOutPut.Text.Trim();
                case ProjectType.Interface:
                    return txtInterfaceOutPut.Text.Trim();
                default:
                    return txtWebOutPut.Text.Trim();
            }
        }

        private void GenerateProjectFile(Engine engine, ProjectType projectType)
        {
            var host = GetTemplateHost(projectType);
            string temp = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("{0}Proejct.tt",projectType)));
            var content = engine.ProcessTemplate(temp, host);
            if (host.Errors.Count > 0)
            {
                foreach (var item in host.Errors)
                {
                    Console.WriteLine(item.ToString());
                }
                return;
            }

            File.WriteAllText(Path.Combine(GetOutputFolder(projectType), string.Format("{0}.csproj", txtNameSpace.Text)), content);
            if(projectType == ProjectType.Entity)
            {
                var edmx = new FileInfo(txtModel.Text);
                var poco = new FileInfo(Path.Combine(txtEntityOutPut.Text, "poco.cs"));
                if (poco.Exists)
                    poco.MoveTo(Path.Combine(txtEntityOutPut.Text, "FixupCollection.cs"));

                edmx.CopyTo(Path.Combine(txtEntityOutPut.Text, edmx.Name), true);
            }


            var path = Path.Combine(GetOutputFolder(projectType), "Properties");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            const string asm = @"using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle(""{0}"")]
[assembly: AssemblyDescription("""")]
[assembly: AssemblyConfiguration("""")]
[assembly: AssemblyCompany(""魔方工作室"")]
[assembly: AssemblyProduct(""{0}"")]
[assembly: AssemblyCopyright(""Copyright © a 2010"")]
[assembly: AssemblyTrademark("""")]
[assembly: AssemblyCulture("""")]
[assembly: ComVisible(false)]
[assembly: Guid(""{1}"")]
[assembly: AssemblyVersion(""2.0.0.0"")]
[assembly: AssemblyFileVersion(""2.0.0.0"")]";
            using (var sw = new StreamWriter(File.OpenWrite(Path.Combine(path, "AssemblyInfo.cs"))))
            {
                sw.WriteLine(string.Format(asm, txtNameSpace.Text, Guid.NewGuid()));
            }

        }

        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                txtModel.Text = openFileDialog1.FileName;
            }

        }

        private void btnShowFolder_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                txtEntityOutPut.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            cmbTemplate.SelectedIndex = 0;
        }

        private void btnRepository_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialogRepository.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.txtRepositoryOutPut.Text = folderBrowserDialogRepository.SelectedPath;
            }
        }

        private void btnService_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialogService.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.txtServiceOutPut.Text = folderBrowserDialogService.SelectedPath;
            }
        }

        private void btnIService_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialogIService.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.txtInterfaceOutPut.Text = folderBrowserDialogIService.SelectedPath;
            }
        }

        private void btnContol_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialogControl.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.txtWebOutPut.Text = folderBrowserDialogControl.SelectedPath;
            }
        }
    }

    public enum ProjectType
    {
        Entity,
        Repository,
        Service,
        Interface,
        MVC,
        AspNet,
        Win,
        WPF,
        Silverlight
    }
}
